<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            overflow: hidden;
        }
    </style>
</head>

<body>
    <canvas id="canvas"></canvas>
</body>
<script id="ColorVS" type="x-shader/x-vertex">
    attribute vec4 a_Position;
    uniform mat4 u_ModelM4;
    uniform mat4 u_PvM4;
    varying vec3 v_Position;
    void main(){
        vec4 worldPosi = u_ModelM4 * a_Position;
        gl_Position = u_PvM4 * worldPosi;
        v_Position = vec3(worldPosi);
    }
</script>
<!-- 直线的 -->
<script id="Color1FS" type="x-shader/x-fragment">
    precision mediump float;
    uniform vec4 u_Color;
    uniform float u_Set;
    uniform vec3 u_Eye;
    varying vec3 v_Position;
    void main(){
        float depth = smoothstep(0.0, 1.0, gl_FragCoord.z);
        float invert = 1.0 - depth;
        float r = distance(v_Position, u_Eye);

        vec3 line = vec3(0.0, 0.0 ,1.0) * (1.0 - smoothstep(0.0, 3.0, r));
        if(abs(depth - u_Set / 3.0) < 0.015){
            gl_FragColor = vec4(line + vec3(invert), 1.0);
        }else{
            gl_FragColor = vec4(vec3(invert), 1.0);
        }
    }
</script>
<!-- 圆形的 -->>
<script id="Color2FS" type="x-shader/x-fragment">
    precision mediump float;
    uniform vec4 u_Color;
    uniform float u_Set;
    uniform vec3 u_Eye;
    varying vec3 v_Position;
    void main(){
        float depth = smoothstep(0.0, 1.0, gl_FragCoord.z);
        float invert = 1.0 - depth;
        
        vec3 eye = vec3(u_Eye.x, 0, u_Eye.z);
        float r = distance(v_Position, eye);

        if(r < u_Set && r > u_Set - 0.01){
            gl_FragColor = vec4(vec3(1.0 - smoothstep(0.0, 3.0, r), 0.0 ,0.0) + vec3(invert), 1.0);
        }else{
            gl_FragColor = vec4(vec3(invert), 1.0);
        }
    }
</script>
<script type="module">
    import { Matrix4, Vector3, Color, OrthographicCamera, PerspectiveCamera, Spherical } from '../js/three.module.js';
    import { CreateProgram, imgPromise } from '../js/Utils.js';
    import lib from '../js/ThreeLib.js';
    import CameraController from '../js/CameraController.js'
    import Poly from '../js/Poly4.js'
    import Control from '../js/Control.js'
    import Square from '../js/objs/Square.js'

    import Geo from '../js/Poly2/Geo.js'
    import Mat from '../js/Poly2/Mat.js'
    import Obj3D from '../js/Poly2/Obj3D.js'
    import Scene from '../js/Poly2/Scene.js'




    //#region gl
    const canvas = document.getElementById("canvas");
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;

    const gl = canvas.getContext("webgl", { antialias: true, });

    gl.enable(gl.BLEND);
    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
    gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);//去图片描边
    gl.enable(gl.DEPTH_TEST);
    //#endregion

    const scene = new Scene({ gl: gl });
    scene.addAxisProgram();
    scene.regProgram('color', {
        program: CreateProgram(gl,
            document.querySelector('#ColorVS').innerText,
            document.querySelector('#Color2FS').innerText),
        attribs: ['a_Position'],
        uniforms: ['u_PvM4', 'u_ModelM4', 'u_Color', 'u_Set', 'u_Eye']
    })


    const pvM4 = new Matrix4();
    const modelM4 = new Matrix4();
    const eye = new Vector3(0, 1.0, 1.7);
    const lookAt = new Vector3(0, 0.3, 0);

    const camera = new PerspectiveCamera(45, canvas.width / canvas.height, 1, 20);
    const cameraController = new CameraController({
        canvas,
        camera,
        pvMatrix: pvM4,
        eye,
        lookAt,
    });


    const axis = new Obj3D().createAxis('axis');
    //scene.add(axis);

    const square = new Square(0.1);
    const [squareVertices, squareElements, squareNormals] = [
        square.vertices, square.elements, square.normals
    ];



    //#region main

    const map = createMap();
    scene.add(map);

    //#endregion


    function createMap(multiple = 1) {
        const map = new Obj3D();

        //墙壁
        const [wallW, wallH] = [1 * multiple, 0.5 * multiple];
        const wall = getFace(wallW, wallH);
        map.add(gl, createObj3D(wall.vertices, wall.elements,
            new Matrix4().multiply(new Matrix4().setPosition(0, wallH, wallW * -1))));
        map.add(gl, createObj3D(wall.vertices, wall.elements,
            new Matrix4().multiply(new Matrix4().setPosition(0, wallH, wallW))));
        map.add(gl, createObj3D(wall.vertices, wall.elements,
            new Matrix4().multiply(new Matrix4().setPosition(wallW * -1, wallH, 0)).multiply(new Matrix4().makeRotationY(90 * Math.PI / 180))));
        map.add(gl, createObj3D(wall.vertices, wall.elements,
            new Matrix4().multiply(new Matrix4().setPosition(wallW, wallH, 0)).multiply(new Matrix4().makeRotationY(90 * Math.PI / 180))));
        //地板
        const [floorW, floorH] = [1 * multiple, 1 * multiple];
        const floor = getFace(floorW, floorH);
        map.add(gl, createObj3D(floor.vertices, floor.elements,
            new Matrix4().multiply(new Matrix4().makeRotationX(90 * Math.PI / 180))));
        //生成小箱子
        map.add(gl, createObj3D(squareVertices, squareElements,
            new Matrix4()
                .multiply(new Matrix4().setPosition(-(-0.1 * 2 + 1) * multiple, 0.1 * 3 * multiple, -(-0.1 * 2 + 1) * multiple))
                .multiply(new Matrix4().makeScale(2 * multiple, 3 * multiple, 2 * multiple))
        ));

        return map;
    }

    function createObj3D(vertices, elements, mm4, color = [1, 1, 1, 1]) {
        return new Obj3D({
            geo: new Geo({
                data: {
                    'a_Position': { size: 3, array: new Float32Array(vertices) },
                },
                element: {
                    array: new Uint16Array(elements)
                }
            }),
            mat: new Mat({
                program: 'color',
                mode: ['TRIANGLES'],
                data: {
                    'u_PvM4': { type: 'uniformMatrix4fv', value: pvM4.elements },
                    'u_ModelM4': { type: 'uniformMatrix4fv', value: mm4.elements },
                    'u_Color': { type: 'uniform4fv', value: color },
                    'u_Set': { type: 'uniform1f', value: 0 },
                    'u_Eye': { type: 'uniform3fv', value: [...eye] },
                },
            }),
        });;
    }


    function getFace(w, h) {
        const [faceVertices, faceElements, faceNormals] = [
            [
                -w, h, 0,
                -w, -h, 0,
                w, -h, 0,
                w, h, 0,
            ], [
                0, 1, 2,
                0, 2, 3,
            ], [
                -w, h, 0,
                -w, -h, 0,
                w, -h, 0,
                w, h, 0,
            ]
        ];
        return { vertices: faceVertices, elements: faceElements };
    }

    let set = 0;
    (function ani(time) {
        set += 0.005;
        //这个3是控制渲染范围的
        if (set > 3) {
            set = 0;
            scene.setUniform('u_Eye', { value: [...eye] });
        }


        scene.setUniform('u_Set', { value: set });

        draw();
        requestAnimationFrame(ani)
    })(0);


    function draw() {
        scene.setUniform('u_PvM4', { value: pvM4.elements });
        scene.draw();
    }
</script>

</html>